package com.example.demo.database.services.system;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class LoadClassService {

    public static List<String> loadClasses(String scan) throws IOException {
        List<String> result = new ArrayList<>();
        scan = scan.replaceAll("\\.", "/");
        Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(scan);
        while (dirs.hasMoreElements()) {
            URL url = dirs.nextElement();
            if (url.getProtocol().equals("file")) {
                List<File> classes = new ArrayList<>();
                // 递归 变量路径下面所有的 class文件
                listFiles(new File(url.getFile()), classes);
                // 加载我们所有的 class的名字
                result = loadClassesName(classes, scan);
            }
        }
        return result;
    }

    /**
     * 载入所有扫描到的类的名字
     *
     * @param classes 类文件
     * @param scan    扫描的包
     * @return
     * @throws ClassNotFoundException
     */
    private static List<String> loadClassesName(List<File> classes, String scan) {
        List<String> clazzes = new ArrayList<>();
        for (File file : classes) {
            // 因为scan 就是/  ， 所有把 file的 / 转成  \   统一都是：  /
            String fPath = file.getAbsolutePath().replaceAll("\\\\", "/");
            // 把 包路径 前面的 盘符等 去掉 ， 这里必须是lastIndexOf ，防止名称有重复的
            String packageName = fPath.substring(fPath.lastIndexOf(scan));
            // 去掉后缀.class ，并且把 / 替换成 .    这样就是  com.hadluo.A 格式了 ， 就可以用Class.forName加载了
            packageName = packageName.replace(".class", "").replaceAll("/", ".");
            // 根据名称加载类
            clazzes.add(packageName);
        }
        return clazzes;

    }

    /**
     * 查找所有的文件
     *
     * @param dir      路径
     * @param fileList 文件集合
     */
    private static void listFiles(File dir, List<File> fileList) {
        if (dir.isDirectory()) {
            //是文件夹则继续递归
            for (File f : dir.listFiles()) {
                listFiles(f, fileList);
            }
        } else {
            //如果是.class结束，说明找到匹配的类，存起来
            if (dir.getName().endsWith(".class")) {
                fileList.add(dir);
            }
        }
    }
}
